package com.hyq.elasticsearchdemo.utils;

import com.alibaba.fastjson.JSON;
import com.hyq.elasticsearchdemo.dao.Hotel;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.UUID;

@Service
public class EsTemplate {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    /**
     * 创建一个索引并设置分片数以及副本数
     * @param indexName 索引名称
     * @param numberOfShards 分片数
     * @param numberOfReplicas 副本数
     * @param filedNameAndType 需要设置的字段及类型(eg:{"name","text";"score":"float";"evaluate":"keyword"})
     * @throws Exception
     */
    public String createIndex(String indexName,String IndexType,Integer numberOfShards,Integer numberOfReplicas,Map<String,String> filedNameAndType) throws Exception {
        // 创建索引请求
        CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName);
        // 设置分片和副本数
        createIndexRequest.settings(Settings.builder()
                .put("index.number_of_shards", numberOfShards) // 分片数设置
                .put("index.number_of_replicas", numberOfReplicas) // 副本数设置
        );

        // 设置文档字段及字段类型
        XContentBuilder mappingBuilder = XContentFactory.jsonBuilder();
        mappingBuilder.startObject();
        {
            mappingBuilder.startObject("properties");
            for (String fileName : filedNameAndType.keySet()) {
                mappingBuilder.startObject(fileName);
                {
                    mappingBuilder.field("type", filedNameAndType.get(fileName));
                }
                mappingBuilder.endObject();
            }
            mappingBuilder.endObject();
        }
        mappingBuilder.endObject();

        createIndexRequest.mapping(IndexType,mappingBuilder);

        // 执行创建请求    IndicesClient,请求后获得响应
        CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
        return createIndexResponse.toString();
    }

    /**
     * 判断该索引是否存在
     * @param indexName 索引名称
     * @return
     * @throws Exception
     */
    public boolean existIndex(String indexName) throws Exception{
        GetIndexRequest indexRequest = new GetIndexRequest(indexName);
        boolean exists = restHighLevelClient.indices().exists(indexRequest, RequestOptions.DEFAULT);
        return exists;
    }

    /**
     * 删除索引
     * @param indexName 索引名称
     * @throws Exception
     */
    public void deleteIndex(String indexName) throws Exception{
        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(indexName);
        AcknowledgedResponse delete = restHighLevelClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
        System.out.println(delete);
    }

    /**
     * 添加文档
     * @param indexName 索引名称
     * @param hotel 实体类
     * @throws Exception
     */
    public String addDocument(String indexName,Hotel hotel) throws Exception {
        //创建请求
        IndexRequest indexRequest = new IndexRequest(indexName);
        //创建规则
        indexRequest.id(UUID.randomUUID().toString());
        indexRequest.timeout(TimeValue.timeValueSeconds(1));
        //超出1s就不执行
        indexRequest.timeout("1s");
        //将数据放入请求 这里使用fastjson的jar包,不过推荐使用hutoool工具类
        IndexRequest source = indexRequest.source(JSON.toJSONString(hotel), XContentType.JSON);
        //客户端发送请求
        IndexResponse index = restHighLevelClient.index(source, RequestOptions.DEFAULT);
        //获取相应的结果
        return index.toString();
    }

    /**
     * 查询文档是否存在
     * @param indexName 索引名称
     * @param _id 文档id
     * @return
     * @throws Exception
     */
    public boolean existDocument(String indexName,String _id) throws Exception {
        GetRequest test_create = new GetRequest(indexName, _id);
        //不获取返回的_source上下文效率更高
        test_create.fetchSourceContext(new FetchSourceContext(false));
        test_create.storedFields("_none_");
        boolean exists = restHighLevelClient.exists(test_create, RequestOptions.DEFAULT);
        return exists;
    }

    /**
     * 更新文档的信息
     * @param indexName 索引名称
     * @param _id 文档id
     * @param hotel 实体类
     * @throws Exception
     */
    public void updateDocument(String indexName,String _id,Hotel hotel) throws Exception {
        UpdateRequest test_create = new UpdateRequest(indexName,_id);
        test_create.doc(JSON.toJSONString(hotel),XContentType.JSON);
        UpdateResponse update = restHighLevelClient.update(test_create, RequestOptions.DEFAULT);
    }

    /**
     * 删除文档
     * @param indexName 索引名称
     * @param _id 文档id
     * @throws Exception
     */
    public void deleteDocument(String indexName,String _id) throws Exception {
        DeleteRequest deleteRequest = new DeleteRequest(indexName,_id);
        restHighLevelClient.delete(deleteRequest,RequestOptions.DEFAULT);
    }
}
